#pragma once

#include "mccommonapi.h"
#include "mcvecvalue.h"

#include <map>
#include <string>

namespace MCCommon
{

class IMCSettingValue;
class MCAPI MCSettings
{
public:
    /**
     * Constructor.
     * 
     */
    MCSettings();

    /**
     * Destructor.
     * 
     */
    ~MCSettings();

    /**
     * Copy constructor.
     * 
     */
    MCSettings
    (
        const MCSettings& other
    );

    /**
     * Assign operator.
     * 
     */
    MCSettings&
    operator = 
    (
        const MCSettings& other 
    );

    /**
     * Create a copy of MCSettings.
     * 
     */
    MCSettings* Clone() const;

    /**
     * Clear all settings.
     * 
     */
    void Clear();

    /**
     * Is having the specified setting.
     * 
     */
    bool IsHavingSetting
    (
        const std::string& name
    ) const;

    /**
     * Add Setting functions.
     * 
     */
    bool AddSetting
    ( 
        const std::string& name, 
        bool value
    );
    bool AddSetting
    ( 
        const std::string& name, 
        int value
    );
    bool AddSetting
    ( 
        const std::string& name, 
        double value
    );
    bool AddSetting
    ( 
        const std::string& name, 
        const std::string& value
    ); 
    bool AddSetting
    ( 
        const std::string& name, 
        const char* value
    );  
    bool AddSetting
    ( 
        const std::string& name, 
        const MCSettings& value  
    );    
    template< class T >
    bool AddSetting
    ( 
        const std::string& name,
        const std::vector< T >& value 
    )
    {
        bool isOK( false );
        
        if ( !IsHavingSetting( name ) )
        {
            IMCSettingValue* pValue = new MCVecValue< T >( value );
            
            isOK = AddSetting( name, pValue );
        }
        
        return isOK;
    }

    /**
     * Get setting functions.
     * 
     */
    bool GetSetting
    ( 
        const std::string& name, 
        bool& value
    ) const;    
    bool GetSetting
    ( 
        const std::string& name, 
        int& value
    ) const; 
    bool GetSetting
    ( 
        const std::string& name, 
        double& value
    ) const;   
    bool GetSetting
    ( 
        const std::string& name, 
        std::string& value
    ) const; 
    bool GetSetting
    ( 
        const std::string& name, 
        MCSettings& value
    ) const; 
    template< class T>
    bool GetSetting
    ( 
        const std::string& name, 
        std::vector< T >& value    
    ) const
    {
        bool isOK( false);

        std::map< std::string, int >::const_iterator it = 
            fNameIndexMap.find( name );
        if ( it != fNameIndexMap.end() )
        {       
            IMCSettingValue* pValue = fSettingValues[ it->second ];
            if ( pValue->GetValueType() == IMCSettingValue::kVT_Vector )
            {
                MCVecValue<T>* pVecList = ( MCVecValue<T>*)pValue;
                if ( pVecList )
                {
                    isOK = true; 
                    value = pVecList->GetVecValues();           
                }            
            }         
        }

        return isOK;       
    }

private:
    
    /**
     * Add setting.
     * 
     */
    bool AddSetting
    ( 
        const std::string& name, 
        IMCSettingValue* value  
    );

private:
    
    // Name-index map.
    std::map< std::string, int > fNameIndexMap;
    
    // Setting values.
    std::vector< IMCSettingValue* > fSettingValues;
};

} // end of namespace MCCommon.
